/**
 * @param { HTMLInputElement|HTMLTextAreaElement } input
 * @returns {Obejct{start, end}}
 */
export function getRange (input) {
  if (typeof input.selectionStart === 'number' && typeof input.selectionEnd === 'number') {
    return {
      start: input.selectionStart,
      end: input.selectionEnd
    };
  } else {
    const range = document.selection.createRange();
    var start = 0;
    var end = 0;

    if (range && range.parentElement() === input) {
      let len = input.value.length;
      let normalizeValue = input.value.replace(/\r\n/g, '\n');

      let textInputRange = input.createTextRange();
      textInputRange.moveToBookmark(range.getBookmark());

      let endRange = input.createTextRange();
      endRange.collapse(false);

      if (textInputRange.compareEndPoints('StartToEnd', endRange) > -1) {
        start = end = len;
      } else {
        start = -textInputRange.moveStart('character', -len);
        start += normalizeValue.slice(0, start).split('\n').length - 1;

        if (textInputRange.compareEndPoints('EndToEnd', endRange) > -1) {
          end = len;
        } else {
          end = -textInputRange.moveEnd('character', -len);
          end += normalizeValue.slice(0, end).split('\n').length - 1;
        }
      }
    }

    return { start, end };
  }
}

/**
 * @param { HTMLInputElement|HTMLTextAreaElement } input
 * @param { Number } start
 * @param { Number } end
 */
export function setRange (input, start, end) {
  end = end || start;
  if (input.setSelectionRange) {
    input.setSelectionRange(start, end);
    input.focus();
  } else if (input.createTextRange) {
    var range = input.createTextRange();
    range.collapse();
    range.moveStart('character', start);
    range.moveEnd('character', end - start);
    range.select();
  }
}

/**
 * @desc IE9, 需要保存 range
 * @param { HTMLInputElement|HTMLTextAreaElement } input
 * @param { String } attr
 */
export function updateRange (input, attr = 'data-range') {
  const range = getRange(input);
  input.setAttribute(attr, range.start);
  return range;
}
